package com.ly.common.security.service;

import cn.hutool.core.lang.UUID;
import com.ly.common.core.constants.CacheConstants;
import com.ly.common.core.constants.JwtConstants;
import com.ly.common.redis.service.RedisService;
import com.ly.common.core.domain.LoginUser;
import com.ly.common.core.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

//操作用户登录token的方法
@Service
@Slf4j
public class TokenService {

    @Autowired
    private RedisService redisService;
    public String createToken(Long userId,String secret,Integer identity,String nickName,String headInmage){

        //生成JWT token的方法
        Map<String,Object> claims=new HashMap<>();

        String userKey= UUID.fastUUID().toString();

        claims.put(JwtConstants.LOGIN_USER_ID,userId);
        claims.put(JwtConstants.LOGIN_USER_KEY,userKey);

//            secret定期更换,不能写死,写在nacos上
        String token= JwtUtils.createToken(claims,secret);
        //往第三方存储敏感信息 redis

        //身份认证具体要存储哪些信息表明用户身份字段 identity 1 表示普通用户 2表示管理员用户

        //但是最好是可扩展的,所以设置为对象

        //使用什么样的数据结构 String  key-value

        //key必须保证唯一,便于维护=>统一前缀+logintoken:userId  userId通过雪花算法生成的唯一的字符串

        //主键若为自增,redis存储所用用户登录信息(包括管理员和C端用户)

        //hutool提供的工具类(uuid可以理解为全局唯一标识)
        String tokenkey = getTokenKey(userKey);
//            String key ="logintoken:" + sysUser.getUserId();
        //记录过期时间,过期时间定义多长 Redis如果能查出来则没过期,不存在则过期
        LoginUser loginUSer=new LoginUser();
        loginUSer.setIdentity(identity);
        loginUSer.setNickName(nickName);
        loginUSer.setHeadImage(headInmage);
        redisService.setCacheObject(tokenkey,loginUSer, CacheConstants.EXP, TimeUnit.MINUTES);
        return token;
    }

    //延长token的有效时间,延长redis存储的用于身份认证的敏感信息的有效时间  操作redis  token=>拿到key(唯一标识)

    //在身份验证之后执行,并且请求到达controller层之前,在拦截器中调用


    public void extendToken(Claims claims){
       //理论上出现问题的概率为0,但是若是错了,直接看日志即可
//        Claims claims = null;
//        try {
//           claims = JwtUtils.parseToken(token, secret); //获取令牌中信息 解析payload中信息 存储着用户的唯一表示信息
//            if (claims == null) {
//                log.error("延长token: {} 出现异常",token);
//                return;
//            }
//        } catch (Exception e) {
//            log.error("延长token: {} 出现异常",token,e);
//            return;
//        }
//        String userKey = JwtUtils.getUserKey(claims); //获取jwt中的key
        String userKey = getUserKey(claims);
        if (userKey==null){
            return;
        }

        String tokenkey = getTokenKey(userKey);
        //寻找临界值延长,而不是无脑延长  720min=>12个小时 剩余三个小时就进行延长
        Long expire=redisService.getExpire(tokenkey,TimeUnit.MINUTES);
        if (expire!=null&&expire<CacheConstants.REFRESH_TIME){
            redisService.expire(tokenkey,CacheConstants.EXP,TimeUnit.MINUTES);
        }

    }
    public boolean deleteLoginUser(String token, String secret) {
        String userKey = getUserKey(token, secret);
        if(userKey==null){
            return false;
        }
        return redisService.deleteObject(getTokenKey(userKey));
    }

    public LoginUser getLoginUser(String token,String secret) {
        String userKey = getUserKey(token, secret);
        if(userKey==null){
            return null;
        }
        return redisService.getCacheObject(getTokenKey(userKey),LoginUser.class);
    }

    private String getTokenKey(String userKey){
        return CacheConstants.LOGIN_TOKEN_KEY + userKey;

    }

    public Long getUserId(Claims claims){
        if(claims==null){
            return null;
        }
        return Long.valueOf(JwtUtils.getUserId(claims)); //获取jwt中的key

    }
    public   String getUserKey(Claims claims){
        if (claims == null) return null;
        return JwtUtils.getUserKey(claims); //获取jwt中的key
    }

    public   String getUserKey(String token ,String secret){
        Claims claims = getClaims(token, secret);
        if (claims == null) return null;
        return JwtUtils.getUserKey(claims); //获取jwt中的key
    }

    public Claims getClaims(String token, String secret) {
        Claims claims;
        try {
            claims = JwtUtils.parseToken(token, secret); //获取令牌中信息 解析payload中信息 存储着用户的唯一表示信息
            if (claims == null) {
                log.error("延长token: {} 出现异常", token);
                return null;
            }
        } catch (Exception e) {
            log.error("延长token: {} 出现异常", token,e);
            return null;
        }
        return claims;
    }

    public void refreshLoginUser(String nickName, String headImage, String userKey) {
        String tokenKey = getTokenKey(userKey);
        LoginUser loginUser = redisService.getCacheObject(getTokenKey(userKey), LoginUser.class);
        loginUser.setNickName(nickName);
        loginUser.setHeadImage(headImage);
        redisService.setCacheObject(tokenKey,loginUser);
    }
}
